declare var Raphael;
/**
 * Generated class for the DeviceIndexCircleComponent component.
 *
 * See https://angular.io/api/core/Component for more info on Angular
 * Components.
 */
import { Injectable } from '@angular/core';
@Injectable()
export class DeviceIndexCircleService {
  defaultOption = {
    domId: 'holder',
    defaultAngle: 0,

    // 当前值与最大值
    label: '',
    value: '',
    unit: '',
    total: '100',

    // 画布大小
    width: 280,
    height: 280,

    // 圆心图片
    img: 'ionic.png',
    imgWidth: 80,
    imgHeight: 80,

    // 范围数组
    dataArray: [
      { startAngle: 0, endAngle: 90, color: '#555' },
      { startAngle: 90, endAngle: 240, color: '#00ff00' },
      { startAngle: 240, endAngle: 290, color: '#FFD700' },
      { startAngle: 290, endAngle: 360, color: '#ff0000' },
    ],

    // top
    top: {
      label: '',
      value: '',
      unit: '',
    },

    // bottom
    bottom: {
      label: '',
      value: '',
      unit: '',
    },

    // left
    left: {
      label: '',
      value: '',
      unit: '',
    },

    // right
    right: {
      label: '',
      value: '',
      unit: '',
    },
    // other info
    other: {
      label: '',
      value: '',
      unit: '',
    },

    // 数值范围
    range: { start: 50, end: 80 },

    startAngle: 30,
    endAngle: 330,

    // 蓄电池
    batSrc: '',
  };

  option: any;

  constructor() {
    console.log('Hello DeviceIndexCircleComponent Component');
    Raphael.el.addClass = function(className) {
      this.node.setAttribute('class', className);
      return this;
    };
  }

  init(seft_options) {
    this.option = {};
    // 合并属性
    this.option = this.deepCopy(this.defaultOption);
    // 合并属性
    for (const proName in seft_options) {
      if (proName) {
        this.option[proName] = seft_options[proName];
      }
    }

    // 属性转换
    if (this.option.value > 100) {
      this.option.value = 100;
    }
    this.option.range.start =
      30 + (this.option.range.start / this.option.total) * 300;
    this.option.range.end =
      30 + (this.option.range.end / this.option.total) * 300;

    // 初始化画布
    const r = Raphael(
      this.option.domId,
      this.option.width,
      this.option.height + 10
    );

    this.addCustomerAttribute(r);

    const outCircle = r
      .path()
      .attr({
        'stroke-width': 1,
        'stroke': '#fff'
      })
      .attr({ arc: [10, 12, this.option.height / 2 - 5] })
      .attr({ transform: 'R210' });
    outCircle.addClass('device-monitor-out-circle');

    // 小实心圈
    let circleColor = '#1E90FF';
    if (this.option.value !== '') {
      const position = 30 + (this.option.value / this.option.total) * 300;
      const y_position = this.option.height - 23;
      const dataArrLength = this.option.dataArray.length;
      // 确定小圈颜色
      for (let i = 0; i < dataArrLength; i++) {
        const dataModel = this.option.dataArray[i];
        if (dataModel.startAngle < position && dataModel.endAngle > position) {
          circleColor = dataModel.color;
          this.option.color = circleColor;
        }
      }

      r.circle(this.option.width / 2, y_position, 4).attr({
        fill: circleColor,
        'fill-opacity': 0.5,
        'stroke-width': 0,
        transform:
          'r' +
          position +
          ' ' +
          this.option.width / 2 +
          ' ' +
          this.option.height / 2,
      });
    }

    // 内圈图片
    const pxPerRem = (document.documentElement.clientWidth * 1) / 10;
    const imgRealWidth = 148 / (75 / pxPerRem);

    const promise = new Promise((resolve, reject) => {
      const testImg = new Image();
      testImg.onerror = function() {
        reject();
      };
      testImg.onload = function() {
        resolve();
      };
      testImg.src = this.option.img;
    });

    // TODO: 修复 then 引起的问题
    promise
      .then(
        () => {},
        () => {
          this.option.img = 'assets\\imgs\\device\\default.png';
        }
      )
      .then(() => {
        const img = r
          .image(
            this.option.img,
            this.option.width / 2 - imgRealWidth / 2,
            this.option.height / 2 - imgRealWidth / 2,
            imgRealWidth,
            imgRealWidth
          )
          .attr({ opacity: this.option.opacity || 1 });
        img.addClass('device-monitor-center-img');
        // 画图
        this.render(r);
        // 显示参数值
        this.drawText(r);
      });
  }

  // 作图
  render(r) {
    let angle = this.option.defaultAngle;
    const startAngle = this.option.startAngle;
    const endAngle = this.option.endAngle;

    const width = this.option.width;
    const height = this.option.height;

    const range = this.option.range;

    let c, t;
    while (angle < 360) {
      if (angle <= startAngle || angle > endAngle) {
        angle += 3;
      } else {
        const dataArray = this.option.dataArray;
        const dataLength = dataArray.length;

        for (let i = 0; i < dataLength; i++) {
          if (
            dataArray[i].startAngle <= angle &&
            dataArray[i].endAngle > angle
          ) {
            c = dataArray[i].color;

            t = 'r' + angle + ' ' + width / 2 + ' ' + height / 2;
            if (range.start < angle && range.end > angle) {
              r.rect(width / 2, height - 16, 0.4, 10).attr({
                stroke: c,
                fill: c,
                transform: t,
                'fill-opacity': 0.4,
                'stroke-opacity': 0.8,
              });
            } else {
              r.rect(width / 2, height - 16, 0.05, 10).attr({
                stroke: c,
                fill: c,
                transform: t,
                'fill-opacity': 0.4,
                'stroke-opacity': 0.5,
              });
            }
          }
        }
        angle += 5;
      }
    }
  }

  // 显示参数值
  drawText(r) {
    // === 本身 ===
    const Value_Label_Text = r.text(
      this.option.width / 2,
      this.option.height + 4,
      this.option.label
    );
    Value_Label_Text.attr({
      fill: '#777',
      'text-anchor': 'middle',
      'font-size': '10',
    });
    Value_Label_Text.addClass('value-label-text');

    const ValueText = r.text(
      this.option.width / 2,
      this.option.height - 20,
      this.option.value
    );
    ValueText.attr({
      fill: this.option.color || '#25990e',
      'text-anchor': 'middle',
      'font-size': '36',
    });
    if (this.option.value === 100) {
      ValueText.addClass('value-text-small');
    } else {
      ValueText.addClass('value-text');
    }

    const Value_Unit_Text = r.text(
      this.option.width / 2 + 25,
      this.option.height - 30,
      this.option.unit
    );
    Value_Unit_Text.attr({
      fill: '#777',
      'text-anchor': 'middle',
    });
    Value_Unit_Text.addClass('value-unit-text');

    // === 顶部 ===
    r.text(this.option.width / 2, 25, this.option.top.label).attr({
      font: '12px Fontin-Sans, Arial',
      fill: '#888',
      'text-anchor': 'middle',
      opacity: 0.4,
    });
    r.text(this.option.width / 2, 38, this.option.top.value).attr({
      font: '14px Fontin-Sans, Arial',
      fill: '#00ff25',
      'text-anchor': 'middle',
    });
    // unit
    let shift = (this.option.top.value.length / 2) * 8;
    r.text(this.option.width / 2 + shift, 38, this.option.top.unit).attr({
      fill: '#888',
      'text-anchor': 'start',
      opacity: 0.4,
    });

    // === 底部 ===
    // name -(6.5*wordSpace_name)
    r.text(
      this.option.width / 2,
      this.option.height - 30,
      this.option.bottom.label
    ).attr({
      font: '12px Fontin-Sans, Arial',
      fill: '#888',
      'text-anchor': 'middle',
      opacity: 0.4,
    });
    // value -wordSpace_value*5
    r.text(
      this.option.width / 2 - 4,
      this.option.height - 33,
      this.option.bottom.value
    ).attr({
      font: '14px Fontin-Sans, Arial',
      fill: '#29973a',
      'text-anchor': 'middle',
    });
    // unit
    shift = (this.option.bottom.value.length / 2) * 8;
    r.text(
      this.option.width / 2 + shift - 4,
      this.option.height - 33,
      this.option.bottom.unit
    ).attr({
      fill: '#888',
      'text-anchor': 'start',
      opacity: 0.4,
    });
    if (this.option.batSrc !== '') {
      r.image(
        this.option.batSrc,
        this.option.width / 2 - 25,
        this.option.height - 53,
        47,
        32
      );
    }

    // === 左边 ===
    // name
    r.text(
      this.option.width / 2 - this.option.imgWidth / 2 + 4,
      this.option.height / 2 + 10,
      this.option.left.label
    ).attr({
      font: '10px Fontin-Sans, Arial',
      fill: '#888',
      'text-anchor': 'middle',
      opacity: 0.4,
    });
    // value
    r.text(
      this.option.width / 2 - this.option.imgWidth / 2,
      this.option.height / 2 - 6,
      this.option.left.value
    ).attr({
      fill: '#29973a',
      'text-anchor': 'middle',
    });
    // unit
    r.text(
      this.option.width / 2 - this.option.imgWidth / 2 + 12,
      this.option.height / 2 - 6,
      this.option.left.unit
    ).attr({
      fill: '#888',
      'text-anchor': 'start',
      opacity: 0.4,
    });

    // === 右边 ===
    // name
    r.text(
      this.option.width / 2 + this.option.imgWidth / 2 - 8,
      this.option.height / 2 + 8,
      this.option.right.label
    ).attr({
      font: '12px Fontin-Sans, Arial',
      fill: '#888',
      'text-anchor': 'start',
      opacity: 0.4,
    });
    // value
    r.text(
      this.option.width / 2 + this.option.imgWidth / 2 - 8,
      this.option.height / 2 - 6,
      this.option.right.value
    ).attr({
      fill: '#29973a',
      'text-anchor': 'start',
    });
    // unit
    shift = this.option.right.value.length * 5;
    r.text(
      this.option.width / 2 + this.option.imgWidth / 2 + shift,
      this.option.height / 2 - 6,
      this.option.right.unit
    ).attr({
      fill: '#888',
      'text-anchor': 'end',
      opacity: 0.4,
    });

    // === 其他 ===
    // value
    r.text(
      this.option.width / 2,
      this.option.height + 20,
      this.option.other.value
    ).attr({
      font: '14px Fontin-Sans, Arial',
      fill: '#888',
      'text-anchor': 'middle',
      opacity: 0.4,
    });
  }

  addCustomerAttribute(r) {
    r.customAttributes.arc = (value, total, R) => {
      const alpha = (360 / total) * value,
        a = ((90 - alpha) * Math.PI) / 180,
        x = this.option.width / 2 + R * Math.cos(a),
        y = this.option.height / 2 - R * Math.sin(a);
      // color = c,//"hsb(".concat(Math.round(R) / 200, ",", value / total, ", .75)"),
      let path;
      if (total === value) {
        path = [
          ['M', this.option.width / 2, this.option.height / 2 - R],
          [
            'A',
            R,
            R,
            0,
            1,
            1,
            this.option.width / 2,
            this.option.height / 2 - R,
          ],
        ];
      } else {
        path = [
          ['M', this.option.width / 2, this.option.height / 2 - R],
          ['A', R, R, 0, +(alpha > 180), 1, x, y],
        ];
      }
      return { path: path }; // , stroke: color
    };
  }

  deepCopy(sObj) {
    if (typeof sObj !== 'object') {
      return sObj;
    }
    let s = {};
    if (sObj.constructor === Array) {
      s = [];
    }
    for (const i in sObj) {
      if (i) {
        s[i] = this.deepCopy(sObj[i]);
      }
    }
    return s;
  }
}
